#!/usr/bin/python
# -*- coding: utf-8 -*-


import usb  # requires pyusb available at https://sourceforge.net/projects/pyusb/files/

import sys
import time

import threading # Usada para hilos
import gobject  #  Se requiere un hilo para monitorear
                #  constantemente lo que se recibe



gobject.threads_init() # Inicializar hilos

# Hilo para monitorear info recibida de Pinguino
class ReadThread(threading.Thread):
    # Parametros:
    #  - pingu: Interfaz Pinguino
    #  - buffertext: Buffer de texto a depositar informacin recibida
    def __init__(self, pingu):
        super(ReadThread, self).__init__()
        self.pingu = pingu
        self.quit = False
        self.lock = threading.Lock()

    def read_data(self):
        data = self.pingu.read(100, 100)
        if len(data) > 0:
            self.lock.acquire()
            try:
                self.pingu.RXbuffer.extend(data)
            finally:
                self.lock.release()

    def run(self):
        while not self.quit:
            self.read_data()

    def getLock(self):
        return self.lock


# Hilo para monitorear la entrada de teclado
class ReadStdin(threading.Thread):
    # Parametros:
    #  - pingu: Interfaz Pinguino

    def __init__(self, pingu):
        super(ReadStdin, self).__init__()
        self.pingu = pingu
        self.quit = False
        self.lock = threading.Lock()

    def read_data(self):
        data = sys.stdin.readline()
        if len(data) > 1:
            self.lock.acquire()
            try:
               self.pingu.RTbuffer.append(data.strip("\n"))
            finally:
               self.lock.release()

    def run(self):
        while not self.quit:
            self.read_data()

    def getLock(self):
        return self.lock


class Pinguino():


    VENDOR = 0x04D8
    PRODUCT = 0xFEAA

    CONFIGURATION = 3
    INTERFACE = 0
    ENDPOINT_IN = 0x82
    ENDPOINT_OUT = 0x01

    device = None
    handle = None
    RXbuffer = []
    RTbuffer = []


    def __init__(self,):
        for bus in usb.busses():
            for dev in bus.devices:
                if dev.idVendor == self.VENDOR and dev.idProduct == self.PRODUCT:
                    self.device = dev
                    print "Device found. Vendor %x - Product %x" % (self.VENDOR, self.PRODUCT)
        return None

    def open(self):
        if not self.device:
            print "Error: Device %x:%x: Unable to find device!" % (self.VENDOR, self.PRODUCT)
            return None
        try:
            self.handle = self.device.open()
            self.handle.setConfiguration(self.CONFIGURATION)
            self.handle.claimInterface(self.INTERFACE)
        except usb.USBError, err:
            print err
            self.handle = None
        return self.handle

    def close(self):
        try:
            self.handle.releaseInterface()
        except Exception, err:
            print err
        self.handle, self.device = None, None

    def read(self, length, timeout = 0):
        stringRX = ''
        try:
            stringRX = self.handle.bulkRead(self.ENDPOINT_IN, length, timeout)
        except usb.USBError as err:
            pass
        return stringRX

    def write(self, buffer, timeout = 0):
        return self.handle.bulkWrite(self.ENDPOINT_OUT, buffer, timeout)



if __name__ == '__main__':

    SET_COMMAND = 0xAA
    SET_TRAILER = 0x55
    
    GET_COMMAND = 0xF0
    GET_TRAILER = 0x0F
    
    pinguino = Pinguino()
    if pinguino.open() == None:
        exit(1)

    quit = False

    r = ReadThread(pinguino)
    rx_lock = r.getLock()
    r.start()

    t = ReadStdin(pinguino)
    rt_lock = t.getLock()
    t.start()
    
    while(not quit):
        rx_lock.acquire()
        try:
            if len(pinguino.RXbuffer) > 0:
                print pinguino.RXbuffer
                pinguino.RXbuffer = []
        finally:
            rx_lock.release()

        rt_lock.acquire()
        try:
            if len(pinguino.RTbuffer) > 0:
                data = pinguino.RTbuffer.pop()
                if not data == "quit":
                    send_data = chr(0xF0) + chr(0x06) + chr(0x00) + chr(0x00) + chr(0x0F)
                    print "Enviando " + send_data
                    pinguino.write(send_data, 100)
                    while len(pinguino.RXbuffer) == 0:
                        pass
                else:
                    quit = True
        finally:
            rt_lock.release()


    r.quit = True
    t.quit = True
    pinguino.close()
    print "Saliendo"
    exit(0)
